package edu.intprog.egreeting;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import edu.intprog.configuration.ConfigurationManager;
import edu.intprog.egreeting.basic.EgreetingBaseServlet;
import edu.intprog.egreeting.beans.Greeting;
import edu.intprog.egreeting.beans.GreetingHistory;
import edu.intprog.egreeting.beans.Messages;
import edu.intprog.egreeting.beans.UserDef;
import edu.intprog.mail.BaseMailer;
import edu.intprog.mail.GreetingMailer;
import edu.intprog.sql.SessionManager;

/**
 * Servlet implementation class for Servlet: VnSGreetingServlet
 *
 */
public class VnSGreetingServlet extends EgreetingBaseServlet implements javax.servlet.Servlet {
	static final long serialVersionUID = 1L;

	/* (non-Java-doc)
	 * @see javax.servlet.http.HttpServlet#HttpServlet()
	 */
	public VnSGreetingServlet() {
		super();
	}   	

	/**
	 * doGet
	 * 
	 * This function will be called when a recipient clicks on the greeting link in an email
	 * 
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String greetingId = request.getParameter(GreetingMailer._greetingIdParamName);
		if (greetingId==null)
		{
			//simple security measure
			getServletContext().getRequestDispatcher("/StartServlet").forward(request, response);
			return;
		}

		GreetingHistory greetingHistory = null;

		//get the requested greeting from the DB
		Transaction tx = null;
		Session session = SessionManager.getCurrentSession();
		tx = session.beginTransaction();
		Query query = session.createQuery("from edu.intprog.egreeting.beans.GreetingHistory where GID=:greetingId");
		query.setString("greetingId",greetingId);
		@SuppressWarnings("unchecked")
		List<GreetingHistory> result = (List<GreetingHistory>) query.list();
		tx.commit();

		if (result.size()!=1)
		{
			//some error was detected - report it to the user
			Messages error = new Messages();
			error.set_errorMessage("This greeting does not exist.<br/>");
			request.setAttribute("msgs", error);
			getServletContext().getRequestDispatcher("/messages.jsp").forward(request, response);
			return;
		}

		//mark the greeting as approved (the recipient read the greeting)
		//and update it in the DB
		greetingHistory = result.get(0);

		greetingHistory.set_approved(true);
		greetingHistory.set_approvedDate(new Date());

		session = SessionManager.getCurrentSession();
		tx = session.beginTransaction();

		try
		{
			session.update(greetingHistory);
			tx.commit();
		}
		catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();
		}
		
		//add the greeting required data into the request
		ConfigurationManager.fillRequestWithGreetingEssentials(request);
		ConfigurationManager.prepareGreetingForPreview(greetingHistory, request);
		getServletContext().getRequestDispatcher("/showGreeting.jsp").forward(request, response);
	}

	/* (non-Java-doc)
	 * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		if( request.getSession().getAttribute("user")==null)
		{
			//simple security measure
			getServletContext().getRequestDispatcher("/StartServlet").forward(request, response);
			return;
		}

		//remove the current greeting from the session if such exist
		request.getSession().removeAttribute("greetingTemplate");

		if (request.getParameter("cancel")!=null)
		{
			//cancel was pressed
			getServletContext().getRequestDispatcher("/welcomeGreeting.jsp").forward(request, response);
			return;
		}

		Greeting greeting = null;
		if (request.getParameter("preview")!=null || request.getParameter("searchByName")!=null)
		{
			//preview or search by name was pressed
			greeting = new Greeting();
		}
		else
		{
			greeting = new GreetingHistory();
		}

		//add the greeting required data into the request
		ConfigurationManager.fillRequestWithGreetingEssentials(request);

		//extract the greeting data from the JSP
		greeting.set_senderName( (String) request.getParameter("senderName") );
		greeting.set_senderEmail( ((UserDef) request.getSession().getAttribute("user")).get_emailAddr() );
		greeting.set_recipientName( (String) request.getParameter("RecipientName") );
		greeting.set_recipientEmail( (String) request.getParameter("recipientEmail") );
		greeting.set_backgroundImage( (String) request.getParameter("backImage") );
		greeting.set_backgroundSound( (String) request.getParameter("backMusic") );
		greeting.set_personalBlessing( (String) request.getParameter("personalBlessing") );
		greeting.set_blessing( (String) request.getParameter("blessing") );
		greeting.set_title( (String) request.getParameter("title") );
		greeting.set_greetingImage( (String) request.getParameter("foreImage") );

		if (request.getParameter("searchByName")!=null)
		{
			//search was pressed
			handleSearch(greeting.get_recipientName(), request);
			request.getSession().setAttribute("greetingTemplate", greeting); //save the current greeting data for later 
			getServletContext().getRequestDispatcher("/searchByName.jsp").forward(request, response);
			return;
		}

		//check that the greeting fields were filled properly
		String validationResult = greeting.validate();

		if (validationResult.length()>0)
		{
			//some error was detected
			Messages msgDef = new Messages();
			msgDef.set_errorMessage(validationResult);
			request.setAttribute("msgs", msgDef);
			request.getSession().setAttribute("greetingTemplate", greeting); //this will refill the greeting fields with the "bad" data
			getServletContext().getRequestDispatcher("/greetingTemplate.jsp").forward(request, response);
			return;
		}
		if (request.getParameter("preview")!=null)
		{
			//preview was pressed
			ConfigurationManager.prepareGreetingForPreview(greeting, request);
			getServletContext().getRequestDispatcher("/greetingPreview.jsp").forward(request, response);
			return;
		}
		if (request.getParameter("send")!=null)
		{
			//send was pressed
			handleSend((GreetingHistory) greeting, request);
			getServletContext().getRequestDispatcher("/welcomeGreeting.jsp").forward(request, response);
			return;
		}
	}

	/**
	 * handleSearch
	 * 
	 * this function searches the given recipient name as a part of first or last names
	 * results are added to the request as an attribute
	 * 
	 * @param recipientName - part of the recipient's first or last names to search in the table
	 * @param request - servlet request
	 */
	private void handleSearch(String recipientName, HttpServletRequest request)
	{
		//search was pressed - get all of the user names and emails
		//which answer to the following criteria:
		//the data that is in the Recipient Name field is a part
		//of the sender first name or last name
		Properties emailsAndNames = new Properties(); 
		Transaction tx = null;
		Session session = SessionManager.getCurrentSession();
		try {
			session = SessionManager.getCurrentSession();
			tx = session.beginTransaction();
			Query query = session.createQuery("from edu.intprog.egreeting.beans.UserDef where F_NAME like :fName or L_NAME like :lName");
			query.setString("fName", "%" + recipientName + "%");
			query.setString("lName", "%" + recipientName + "%");
			@SuppressWarnings("unchecked")
			List<UserDef> userResults = (List<UserDef>) query.list();
			tx.commit();

			//add the email as key and the name as a value
			for (int i=0; i<userResults.size(); ++i)
			{
				emailsAndNames.put(userResults.get(i).get_emailAddr(), userResults.get(i).get_fName() + " " +userResults.get(i).get_lName());
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();
			//sql error - report it to the user
			Messages error = new Messages();
			error.set_errorMessage(e.getMessage());
			request.setAttribute("msgs", error);
		}
		request.getSession().setAttribute("searchResults", emailsAndNames);
	}

	/**
	 * handleSend
	 * 
	 * This function send the greeting e-mail and update the DB of a sent greeting
	 * 
	 * @param greetingHistory - greeting to sent and be saved to the DB
	 * @param request - servlet request
	 */
	private void handleSend(GreetingHistory greetingHistory, HttpServletRequest request)
	{
		String errorMessage = new String();
		String successfullMessage = new String();
		Messages msgs = new Messages();
		
		//update the sent date
		greetingHistory.set_sentDate(new Date());

		Transaction tx = null;
		Session session = SessionManager.getCurrentSession();
		try {
			//add the greeting to the history DB
			tx = session.beginTransaction();
			session.save(greetingHistory);
			tx.commit();

			//send the greeting mail
			BaseMailer.initilizeMailConfigurationFromFile(request);
			GreetingMailer gm = new GreetingMailer(greetingHistory.get_senderEmail(),
					greetingHistory.get_recipientEmail(),
					greetingHistory.get_gid().toString(),
					greetingHistory.get_senderName());
			errorMessage = gm.sendMail(request.getRequestURL().toString());

			if(errorMessage.length()>0)
			{
				//error was found during send mail - update the greeting history to mention that it was not sent yet
				greetingHistory.set_sentDate(null);
				session = SessionManager.getCurrentSession();
				tx = session.beginTransaction();
				session.update(greetingHistory);
				tx.commit();
				errorMessage = errorMessage + "The greeting was saved to the greeting history non-the-less<br />";
				msgs.set_errorMessage(errorMessage);
			}
			else
			{
				//the greeting was sent successfully - notify the user
				successfullMessage = "Your greeting was sent successfuly.";
				msgs.set_infoMessage(successfullMessage);
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			if (tx != null && tx.isActive())
				tx.rollback();
			//sql error
			errorMessage = errorMessage + e.getMessage() + "<br />";
			msgs.set_errorMessage(errorMessage);
		}

		request.setAttribute("msgs", msgs);
	}
}